home *** CD-ROM | disk | FTP | other *** search
/ Info-Mac 4 / Info_Mac IV CD-ROM (Pacific HiTech Inc.)(August 1994).iso / Development / Source / POVSRC / SOURCE / ScreenUtils.c < prev    next >
Text File  |  1994-02-04  |  10KB  |  296 lines

  1. /*
  2. ==============================================================================
  3. Project:    POV-Ray
  4.  
  5. Version:    2.2
  6.  
  7. File Name:    ScreenUtils.c
  8.  
  9. Description:
  10.     General-purpose screen/device routines.
  11.  
  12.     This is the main source file, containing the private definitions and
  13.     code to implement all the needed external and internal support functions.
  14.  
  15. Related Files:
  16.     ScreenUtils.h    - Header for these routines
  17. ------------------------------------------------------------------------------
  18. Author:
  19.     Eduard [esp] Schwan
  20. ------------------------------------------------------------------------------
  21.     from Persistence of Vision Raytracer
  22.     Copyright 1993 Persistence of Vision Team
  23. ------------------------------------------------------------------------------
  24.     NOTICE: This source code file is provided so that users may experiment
  25.     with enhancements to POV-Ray and to port the software to platforms other 
  26.     than those supported by the POV-Ray Team.  There are strict rules under
  27.     which you are permitted to use this file.  The rules are in the file
  28.     named POVLEGAL.DOC which should be distributed with this file. If 
  29.     POVLEGAL.DOC is not available or for more info please contact the POV-Ray
  30.     Team Coordinator by leaving a message in CompuServe's Graphics Developer's
  31.     Forum.  The latest version of POV-Ray may be found there as well.
  32.  
  33.     This program is based on the popular DKB raytracer version 2.12.
  34.     DKBTrace was originally written by David K. Buck.
  35.     DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
  36. ------------------------------------------------------------------------------
  37. More Info:
  38.     This Macintosh version of POV-Ray was created and compiled by Jim Nitchals
  39.     (Think 5.0) and Eduard Schwan (MPW 3.2), based (loosely) on the original
  40.     port by Thomas Okken and David Lichtman, with some help from Glenn Sugden.
  41.  
  42.     For bug reports regarding the Macintosh version, you should contact:
  43.     Eduard [esp] Schwan
  44.         CompuServe: 71513,2161
  45.         Internet: jl.tech@applelink.apple.com
  46.         AppleLink: jl.tech
  47.     Jim Nitchals
  48.         Compuserve: 73117,3020
  49.         America Online: JIMN8
  50.         Internet: jimn8@aol.com -or- jimn8@applelink.apple.com
  51.         AppleLink: JIMN8
  52. ------------------------------------------------------------------------------
  53. Change History:
  54.     920826    [esp]    Created
  55.     920903    [esp]    Major cleanup to PositionWindow
  56.     931001    [esp]    version 2.0 finished (Released on 10/4/93)
  57.     931006    [esp]    Fixed ForceRectOnScreen to not let window dangle off lower left
  58. ==============================================================================
  59. */
  60.  
  61. /* Macintosh-specific headers */
  62. #include <Types.h>
  63. #include <QuickDraw.h>
  64. #include <script.h>            // GetMBarHeight() old?
  65. #include <menus.h>            // GetMBarHeight()
  66. #include <Windows.h>        // MoveWindow()
  67.  
  68. #include "ScreenUtils.h"    // our defs
  69.  
  70. // ==============================================
  71. void GetGlobalWindowRect(WindowPtr theWindow, Rect *theRect)
  72. {
  73.     Rect    windRect;
  74.  
  75.     windRect = theWindow->portRect;
  76.  
  77.     // yah, but where is it really?
  78.     SetPort(theWindow);
  79.     LocalToGlobal((Point*)&windRect.top);
  80.     LocalToGlobal((Point*)&windRect.bottom);
  81.  
  82.     *theRect = windRect;
  83. } // GetGlobalWindowRect
  84.  
  85.  
  86. // ==============================================
  87. void ForceRectOnScreen(Rect *aGlobalRect)
  88. {
  89.     long        area;
  90.     long        foundArea;
  91.     GDHandle    aDevice;
  92.     GDHandle    foundDevice;
  93.     Rect        aDeviceRect;
  94.     Rect        foundDeviceRect;
  95.     Rect        intersectRect;
  96.  
  97.     for (aDevice = GetDeviceList(); aDevice != NULL; aDevice = GetNextDevice(aDevice))
  98.     {
  99.         /* If we found an active screen device that intersects some of the rect.. */
  100.         aDeviceRect = (**aDevice).gdRect;
  101.  
  102.         /* See if its the main screen.  If so, take menu bar into account! */
  103.         if ( (**aDevice).gdFlags & (1<<mainScreen) )
  104.         {
  105.             aDeviceRect.top += GetMBarHeight();
  106.             /* also initialize the found device to main device */
  107.             /* in case none found, we default to main device */
  108.             foundDevice = aDevice;
  109.             foundDeviceRect = aDeviceRect;
  110.             foundArea = 0;
  111.         }
  112.  
  113.         /* if it is an active screen... */
  114.         if (TestDeviceAttribute(aDevice, screenDevice)
  115.             && TestDeviceAttribute(aDevice, screenActive)
  116.             && SectRect(aGlobalRect, &aDeviceRect, &intersectRect))
  117.         {
  118.             /* find out how much it intersects */
  119.             area = ((long)intersectRect.right  - (long)intersectRect.left) *
  120.                    ((long)intersectRect.bottom - (long)intersectRect.top);
  121.             /* if intersects more than the last device of intersection, use this instead */
  122.             /* this therefore finds the screen of greatest intersection. */
  123.             if (area > foundArea)
  124.             {
  125.                 foundDevice = aDevice;
  126.                 foundDeviceRect = aDeviceRect;
  127.                 foundArea = area;
  128.             }
  129.         }
  130.     }
  131.  
  132.     /* OK, we have now travelled through all the devices, and 'foundDevice' */
  133.     /* will have the best device to use, or the main device if there were    */
  134.     /* no intersecting screens at all.. Make sure it fits on the screen        */
  135.  
  136.     /* If there is not enough area showing, then move the window to better    */
  137.     /* position on 'foundDevice' (1600 is width<40> X height<40> pixels).    */
  138.     /* Also do this if the top of the window (minus 18 for the title bar)    */
  139.     /* extends above the top of the window (user can't get ahold of it.)    */
  140.     if ( (foundArea < 1600) || ((aGlobalRect->top-18) < foundDeviceRect.top) )
  141.     {
  142.         /* offset its upper left corner a little from top of screen */
  143.         aDeviceRect = foundDeviceRect;
  144.         OffsetRect(&aDeviceRect, 4, 18+4);
  145.  
  146.         /* figure out what its lower left corner would be */
  147.         aDeviceRect.right = aDeviceRect.left + (aGlobalRect->right - aGlobalRect->left);
  148.         aDeviceRect.bottom = aDeviceRect.top + (aGlobalRect->bottom - aGlobalRect->top);
  149.  
  150.         /* Return this rect as the one to use */
  151.         *aGlobalRect = aDeviceRect;
  152.     }
  153.  
  154.     /* If rect bottom/right sides are still off the screen, inset them to fit */
  155.     if    (aGlobalRect->right > foundDeviceRect.right)
  156.         aGlobalRect->right = foundDeviceRect.right-4;
  157.     if    (aGlobalRect->bottom > foundDeviceRect.bottom)
  158.         aGlobalRect->bottom = foundDeviceRect.bottom-4;
  159.  
  160. } // ForceRectOnScreen
  161.  
  162.  
  163. // ==============================================
  164. // Note that this routine and ForceRectOnScreen() should be sharing code.. later.
  165. GDHandle GetClosestGDevice(const Rect * sourceRectp)
  166. {
  167.     GDHandle    theGDevice;
  168.  
  169.     // find max device this rect intersects
  170.     theGDevice = GetMaxDevice(sourceRectp);
  171.     if (theGDevice == NULL)
  172.     {    // didn't work for some reason, get the regular screen
  173.         theGDevice = GetMainDevice();
  174.     }
  175.  
  176.     return theGDevice;
  177.  
  178. } // GetClosestGDevice
  179.  
  180.  
  181. // ==============================================
  182. void GetMaxGrowRect(WindowPtr wind2Grow, Rect * growRectp)
  183. {
  184.     Rect         rw, rs;
  185.     GDHandle    theGDevice;
  186.  
  187.     // find true/global window pos.
  188.     GetGlobalWindowRect(wind2Grow, &rw);
  189.     // make a teeny rect at the mouse pos, so we can
  190.     // find the GDevice at this point
  191.     rs = rw;
  192.     rs.left = rs.right-1;
  193.     rs.top = rs.bottom-1;
  194.     theGDevice = GetClosestGDevice(&rs);
  195.     // now find the rect bounds of the screen that the grow box is on
  196.     rs = (**theGDevice).gdRect;
  197.     // set max size allowed (upper corner of window to bottom corner of screen)
  198.     // this allows the window to grow just to the bottom corner of the screen
  199.     rw.right    = rs.right - rw.left - 4;
  200.     rw.bottom    = rs.bottom - rw.top - 4;
  201.     // set minimum size allowed
  202.     rw.left        = 40;
  203.     rw.top        = 40;
  204.     // let caller know what we finally decided on
  205.     *growRectp    = rw;
  206. } // GetMaxGrowRect
  207.  
  208.  
  209. // ==============================================
  210. void CenterWindInRect(WindowPtr    wind2Center, Rect outerRect)
  211. {
  212.     short    x, y;
  213.     Rect    windRect;
  214.  
  215.     // figure center of outer rect
  216.     x = (outerRect.left + outerRect.right)  >> 1;
  217.     y = (outerRect.top  + outerRect.bottom) >> 1;
  218.  
  219.     // figure out window's rect
  220.     GetGlobalWindowRect(wind2Center, &windRect);
  221.  
  222.     // now center window around x,y (offset by half window size)
  223.     x = x - ((windRect.right - windRect.left) >> 1);
  224.     y = y - ((windRect.bottom - windRect.top) >> 1);
  225.     MoveWindow(wind2Center, x, y, true);
  226.  
  227. } // CenterWindInRect
  228.  
  229.  
  230. // ==============================================
  231. void PositionWindow(WindowPtr wind2Position, WindCentering_t doCentering, WindPositioning_t whereToShow, WindowPtr passedWindow)
  232. {
  233.     Point        upperCorner;
  234.     Rect        mainRect;
  235.     Rect        windRect;
  236.     Rect        deviceRect;
  237.     Rect        maxDragBounds;
  238.     GDHandle    theGDevice;
  239.  
  240.     if (wind2Position == NULL)
  241.         return;
  242.  
  243.     // Set up bounds for all devices
  244.     SetRect(&maxDragBounds, -32000, -32000, 32000, 32000);
  245.  
  246.     // Find main device bounds
  247.     theGDevice = GetMainDevice();
  248.     mainRect = (**theGDevice).gdRect;
  249.  
  250.     // find the device rectangle to show window on
  251.     switch (whereToShow)
  252.     {
  253.         case eSameAsPassedWindow:
  254.             if (passedWindow)
  255.             {
  256.                 // where's the passed window
  257.                 GetGlobalWindowRect(passedWindow, &windRect);
  258.                 theGDevice = GetClosestGDevice(&windRect);
  259.                 deviceRect = (**theGDevice).gdRect;
  260.                 break;
  261.             }
  262.             // otherwise fall through to main device
  263.  
  264.         case eMainDevice:
  265.             deviceRect = mainRect;
  266.             break;
  267.  
  268.         case eDeepestDevice:
  269.             theGDevice = GetMaxDevice(&maxDragBounds);
  270.             deviceRect = (**theGDevice).gdRect;
  271.             break;
  272.     } // switch
  273.  
  274.     // See if its the main screen.  If so, take menu bar into account!
  275.     if ( (**theGDevice).gdFlags & (1<<mainScreen) )
  276.         deviceRect.top += GetMBarHeight();
  277.  
  278.     // if centering, center on screen using that rect
  279.     // otherwise put in relatively same spot on screen
  280.     if (doCentering == ewcDoCentering)
  281.         CenterWindInRect(wind2Position, deviceRect);
  282.     else
  283.     {
  284.         // where's the window, relative to main screen
  285.         GetGlobalWindowRect(wind2Position, &windRect);
  286.         // find relative spot on new device
  287.         upperCorner.h = windRect.left;
  288.         upperCorner.v = windRect.top;
  289.         // now relative to new screen
  290.         upperCorner.h = upperCorner.h + deviceRect.left;
  291.         upperCorner.v = upperCorner.v + deviceRect.top;
  292.         // move it there
  293.         MoveWindow(wind2Position, upperCorner.h, upperCorner.v, true);
  294.     }
  295. } // PositionWindow
  296.